/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package Visitor;
import Arbori.Nod;
import Functii.Constanta;
import Functii.Cos;
import Functii.Ctg;
import Functii.Exp;
import Functii.Log;
import Functii.Necunoscuta;
import Functii.Putere;
import Functii.Radical;
import Functii.Sin;
import Functii.Tg;
import Operatori.Cat;
import Operatori.Minus;
import Operatori.Plus;
import Operatori.Produs;
/**
 *
 * @author AlinT
 */
public class CalculVisitor extends Visitor{
	double value;
	double startValue;


	public double getValue() {
		return value;
	}

	public void setValue(double value) {
		this.value = value;

	}

        //@requires p.getfStang()!=null
        //@requires p.getfStang()!=null
        //@assignable value=x1+x2
	public void visit(Plus p) {
		if ( p.getfStang() != null && p . getfDrept() != null )
		{
		visit(p.getfStang()) ;
		double x1=getValue();
		visit ( p.getfDrept() ) ;
		double x2=getValue();
		value=x1+x2;
		}

	}

	public CalculVisitor() {
		super();
		value=0;
	}

	public CalculVisitor(double d) {
		super();
		this.startValue=d;
	}
        
	public void visit(Minus m) {
		if ( m.getfStang() != null && m.getfDrept() != null )
		{
		visit(m.getfStang()) ;
		double x1=getValue();
		visit ( m.getfDrept() ) ;
		double x2=getValue();
		value=x1-x2;
		}

	}

	public void visit(Cat c) {
		if ( c.getfStang() != null && c.getfDrept() != null )
		{
		visit(c.getfStang()) ;
		double x1=getValue();
		visit ( c.getfDrept() ) ;
		double x2=getValue();
		if (x2!=0.0)
		value=x1/x2;
		}

	}

	public void visit(Produs p) {
		if ( p.getfStang() != null && p . getfDrept() != null )
		{
		visit(p.getfStang()) ;
		double x1=getValue();
		visit ( p.getfDrept() ) ;
		double x2=getValue();
		value=x1*x2;
		}

	}

	public void visit(Necunoscuta n) {
		this.value=n.getX();

	}

	public void visit(Constanta c) {
		this.value=c.getCt();

	}


	public void visit(Sin s) {
		if ( s.getfStang() != null )
		{
			visit(s.getfStang());
			double d=Math.sin(value);
			value=d;
		}

	}

	public void visit(Cos c) {
		if ( c.getfStang() != null )
		{
			visit(c.getfStang());
			double d=Math.cos(value);
			value=d;
		}
	}
        /**
         * 
         * @param n nodul de tip functie sau operator ce va fi vizitat
         */
	public void visit(Nod n) {
		n.setX(startValue);
		if ( n instanceof Necunoscuta ) this.visit((Necunoscuta)n);
		if ( n instanceof Constanta ) this.visit((Constanta)n);
		if ( n instanceof Plus ) this.visit((Plus)n);
		if ( n instanceof Minus ) this.visit((Minus)n);
		if ( n instanceof Cat ) this.visit((Cat)n);
		if ( n instanceof Produs ) this.visit((Produs)n);
		if ( n instanceof Sin ) this.visit((Sin)n);
		if ( n instanceof Cos ) this.visit((Cos)n);
		if ( n instanceof Tg ) this.visit((Tg)n);
		if ( n instanceof Ctg ) this.visit((Ctg)n);
		if ( n instanceof Radical ) this.visit((Radical)n);
		if ( n instanceof Log ) this.visit((Log)n);
		if ( n instanceof Exp ) this.visit((Exp)n);
                if ( n instanceof Putere) this.visit((Putere) n);
	}

	public void visit(Tg t) {
		if ( t.getfStang() != null )
		{
			visit(t.getfStang());
			double d=Math.tan(value);
			value=d;
		}

	}

	public void visit(Ctg c) {
		if ( c.getfStang() != null )
		{
			visit(c.getfStang());
			double d=1/Math.tan(value);
			value=d;
		}

	}

	public void visit(Log l) {
		if ( l.getfStang() != null )
		{
			visit(l.getfStang());
			double d=Math.log(value);
			value=d;
		}

	}

        public void visit(Putere p) {
		if ( p.getfStang() != null )
		{
		visit(p.getfStang()) ;
		double x1=getValue();
		value=Math.pow(x1, 3);
		}

	}

	public void visit(Exp e) {
		if ( e.getfStang() != null )
		{
			visit(e.getfStang());
			double d=Math.exp(value);
			value=d;
		}

	}

	public void visit(Radical r) {
		if ( r.getfStang() != null )
		{
			visit(r.getfStang());
			double d=Math.sqrt(value);
			value=d;
		}

	}
}